package com.kfm.hotel.controller;

import com.anji.captcha.util.AESUtil;
import com.github.pagehelper.PageInfo;
import com.kfm.hotel.anno.Log;
import com.kfm.hotel.anno.Permission;
import com.kfm.hotel.domain.SysUser;
import com.kfm.hotel.domain.UserRoleDTO;
import com.kfm.hotel.service.SysUserService;
import com.kfm.hotel.util.MD5Util;
import com.kfm.hotel.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.models.auth.In;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

@RestController
@RequestMapping("/sysuser")
@Api(tags = "用户管理", description = "用户管理, sys_user表")
public class SysUserController {

    @Autowired
    private SysUserService service;

    @GetMapping
    @Permission("sys:user")
    @PreAuthorize("hasAuthority('sys:user')")
    public ModelAndView index() {
        ModelAndView modelAndView = new ModelAndView("sysuser/index");
        return modelAndView;
    }

    @GetMapping("/list")
    @Permission("sys:user")
    // hasAuthority 与 hasRole 都是从 UserDetails中的 getAuthorities 找是否有相应的内容前者不需要加 ROLE_ 前缀
//    @PreAuthorize("hasAuthority('sys:user:list')")
    @ApiOperation(value = "用户列表", notes = "用于获取用户列表")
    @ApiResponse(code = 200, message = "success", response = R.class)
    public R list(@ApiParam(value = "分页参数-页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer page,
                  @ApiParam(value = "分页参数-页大小", defaultValue = "10")@RequestParam(defaultValue = "10") Integer limit,
                  @ApiParam(value = "查询条件") SysUser user) {
        PageInfo<SysUser> pageInfo = service.list(user, page, limit);
        return R.ok(pageInfo);
    }


    @GetMapping("/add")
    @PreAuthorize("hasRole('ADMIN')")
    public ModelAndView add() {
        ModelAndView modelAndView = new ModelAndView("sysuser/add");
        return modelAndView;
    }

    @PostMapping("/add")
    @Log(title = "用户管理", businessType = "添加用户")
    public R add(@RequestBody SysUser user) throws Exception {

        int save = service.saveSysUser(user);
        if (save > 0) {
            return R.ok("添加成功");
        } else {
            return R.fail("添加失败");
        }
    }

    @GetMapping("/edit/{id}")
    public ModelAndView edit(@PathVariable("id") Integer id) {
        ModelAndView modelAndView = new ModelAndView("sysuser/edit");
        SysUser byId = service.getById(id);
        modelAndView.addObject("user", byId);
        return modelAndView;
    }

    @PostMapping("/edit")
    @Log(title = "用户管理", businessType = "修改用户")
    public R edit(@RequestBody SysUser user) {
        boolean update = service.updateById(user);
        if (update) {
            return R.ok("修改成功");
        } else {
            return R.fail("修改失败");
        }
    }

    @DeleteMapping("/batchDelete")
    @Log(title = "用户管理", businessType = "删除用户")
    public R batchDelete(@RequestBody List<Integer> ids) {
        List<SysUser> list = new ArrayList<>();
        for (Integer id : ids) {
            SysUser user = new SysUser();
            user.setIsDel(true);
            user.setId(id);

            list.add(user);
        }

        boolean b = service.updateBatchById(list);
        if (b) {
            return R.ok("删除成功");
        } else {
            return R.fail("删除失败");
        }
    }


    /**
     * 测试批量删除
     *
     * @param users
     * @return 前提是：SysUser实体类中的id属性必须有值
     * 我们需要在 SysUser 实体中添加一个 有参构造方法，只有id属性
     */
    @PostMapping("/test")
    public R test(@RequestBody List<SysUser> users) {
        boolean b = service.updateBatchById(users);
        if (b) {
            return R.ok("删除成功");
        } else {
            return R.fail("删除失败");
        }
    }

    @GetMapping("/role/{id}")
    public ModelAndView role(@PathVariable("id")Integer userId){
        ModelAndView mv = new ModelAndView("sysuser/role");
        mv.addObject("userId", userId);
        return mv;
    }

    @PostMapping("/role")
    public R role(@RequestBody UserRoleDTO userRoleDTO){
        service.setUserRole(userRoleDTO);
        return R.ok("设置成功");
    }

    @PostMapping("/import")
    public R importData(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0); // 假设导入的是第一个Sheet

            List<SysUser> list = new ArrayList<>();
            Iterator<Row> rowIterator = sheet.iterator();
            if (rowIterator.hasNext()){
                // 跳过第一行
                rowIterator.next();
            }
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
//                Iterator<Cell> cellIterator = row.cellIterator();
                SysUser user = new SysUser();
                Cell cell = row.getCell(1); // 假设导入的是第一列数据
                if (cell == null) {
                    continue;
                }
                cell.setCellType(CellType.STRING);
                user.setUsername(cell.getStringCellValue());
                Cell cell1 = row.getCell(2); // 假设导入的是第二列数据
                cell1.setCellType(CellType.STRING);
                user.setEmail(cell1.getStringCellValue());
                Cell cell2 = row.getCell(3); // 假设导入的是第三列数据
                cell2.setCellType(CellType.STRING);
                user.setPassword(MD5Util.MD5(cell2.getStringCellValue(), user.getUsername()));
                Cell cell3 = row.getCell(4); // 假设导入的是第四列数据
                cell3.setCellType(CellType.STRING);
                user.setName(cell3.getStringCellValue());
                Cell cell4 = row.getCell(5); // 假设导入的是第五列数据
                cell4.setCellType(CellType.STRING);
                user.setPhone(cell4.getStringCellValue());

                try {
                    // 用户是否存在
                    service.existUsername(user);
                } catch (Exception e) {
                    e.printStackTrace();
                    continue;
                }
                list.add(user);
            }

            // 批量插入数据
            Boolean flag = service.saveBatch(list);

            return flag? R.ok("导入成功"):R.fail("导入失败，请检查数据格式");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/export")
    public ResponseEntity<InputStreamResource> export(Integer type, HttpServletResponse response) throws IOException {
        List<SysUser> list = null;
        String fileName = "demo.xlsx";
        if (type == null) {
            // 查询所有的数据
            list = service.list();
            fileName = "user.xlsx";
        } else {
            list = Collections.emptyList();
        }
        // 通过 poi 将数据写入到 excel 表格中
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("用户信息表");

        // 设置表头
        Row row0 = sheet.createRow(0);
        Cell cell0 = row0.createCell(0);
        cell0.setCellValue("id");
        Cell cell1 = row0.createCell(1);
        cell1.setCellValue("用户名");
        Cell cell2 = row0.createCell(2);
        cell2.setCellValue("邮箱");
        Cell cell3 = row0.createCell(3);
        cell3.setCellValue("密码");
        Cell cell4 = row0.createCell(4);
        cell4.setCellValue("真实姓名");
        Cell cell5 = row0.createCell(5);
        cell5.setCellValue("手机号");
        if (type == null) {
            // 导出全部
            Cell cell6 = row0.createCell(6);
            cell6.setCellValue("创建时间");
            CellStyle cellStyle = workbook.createCellStyle();
            // 设置宽度
            sheet.setColumnWidth(6, 20 * 256);
            // 文字居中
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cell6.setCellStyle(cellStyle);
            Cell cell7 = row0.createCell(7);
            cell7.setCellValue("修改时间");
            Cell cell8 = row0.createCell(8);
            cell8.setCellValue("是否删除");
            Cell cell9 = row0.createCell(9);
            cell9.setCellValue("状态");
        }


        int rowCount = 1;
        for (SysUser item : list) {
            Row row = sheet.createRow(rowCount++);
            Cell cell = row.createCell(0); // 假设导出到第一列
            cell.setCellValue(item.getId());
            Cell cell10 = row.createCell(1);
            cell10.setCellValue(item.getUsername());
            Cell cell11 = row.createCell(2);
            cell11.setCellValue(item.getEmail());
            Cell cell12 = row.createCell(3);
            cell12.setCellValue(item.getPassword());
            Cell cell13 = row.createCell(4);
            cell13.setCellValue(item.getName());
            Cell cell14 = row.createCell(5);
            cell14.setCellValue(item.getPhone());
            Cell cell15 = row.createCell(6);
            cell15.setCellValue(item.getCreateTime().toLocaleString());
            Cell cell16 = row.createCell(7);
            cell16.setCellValue(ObjectUtils.isEmpty(item.getUpdateTime()) ? "" : item.getUpdateTime().toLocaleString());
            Cell cell17 = row.createCell(8);
            cell17.setCellValue(item.getIsDel());
            Cell cell18 = row.createCell(9);
            cell18.setCellValue(item.getState());
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);

        InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(outputStream.toByteArray()));

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);

        return ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .body(resource);
    }
}
